package sanmubird.club.mock.minenv;

import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.mockito.junit.MockitoJUnitRunner;
import org.springframework.test.util.ReflectionTestUtils;
import sanmubird.club.mock.service.MockDemoService;
import sanmubird.club.mock.service.MockDependencyService;
import sanmubird.club.mock.service.MockNestDependencyService;
import sanmubird.club.mock.service.MockRemoteInvokeService;

/**
 * @author sam
 * @date 2019/12/8 12:05
 * @description 功能描述
 * <p>
 * 在单元测试中，没有启动 spring 框架，此时就需要通过 @InjectMocks完成依赖注入。
 * 注解 @InjectMocks 会将带有 @Spy 和 @Mock 注解的对象尝试注入到被 测试的目标类中。
 * 但是注意： InjectMocks字段是无法注入其他InjectMocks字段的 但可以通过 ReflectionTestUtils 注入的方式 完成注入
 * <p>
 * Usually when you are unit testing, you shouldn't initialize Spring context. So remove Autowiring.
 * 单元测试时 不需要启动 Spring 上下文 请移除 @Autowired 使用 @InjectMocks 来实现注入bean;
 * Usually when you do integration testing, you should use real dependencies. So remove mocking.
 * 在进行继承测试时， 应该使用真实的依赖，请移除 @Mock
 */

@RunWith(MockitoJUnitRunner.class)
public class InjectMocksAnnotationTest2 {

	@Mock
	MockDemoService mockDemoService;

	@Mock
	MockRemoteInvokeService mockRemoteInvokeService;

	@InjectMocks
	MockDependencyService mockDependencyService;

	@InjectMocks
	MockNestDependencyService mockNestDependencyService;

	@Before
	public void setUp() throws Exception {
//		MockitoAnnotations.initMocks(this);
		//通过 ReflectionTestUtils 注入 需要的非public字段数据
		ReflectionTestUtils.setField(mockNestDependencyService, "mockDependencyService", mockDependencyService);
		Mockito.when(mockDemoService.simpleService()).thenReturn("mockDemoService");
		Mockito.when(mockRemoteInvokeService.remoteInvoke()).thenReturn("remoteInvoke");
	}

	@Test
	public void testInjectMocks() {
		final String actual = mockNestDependencyService.dependencyDemo();
		Assert.assertEquals("mockDemoService remoteInvoke", actual);
	}


}
